package ${location}.exception;

import ${location}.common.HttpCode;
import ${location}.common.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.sql.SQLException;
import java.sql.SQLIntegrityConstraintViolationException;


/**
 * @author ${author}
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

	/**
	 * 自定义异常处理方法
	 *
	 * @param exception CustomizeException
	 * @return ResponseResult
	 */
	@ExceptionHandler(CustomizeException.class)
	@ResponseBody
	public <T> ResponseResult<T> exceptionHandler(CustomizeException exception) {
		exception.printStackTrace();
		HttpCode httpCode = exception.getResponseCode();
		log.error("Custom Exception: {}, {}", httpCode.getCode(), exception.getMessage());
		log.error("detailed cause: {}", exception.fillInStackTrace());
		return ResponseResult.error(httpCode, exception.getMessage());
	}

	/**
	 * 处理不可控异常
	 *
	 * @param ex Exception
	 * @return ResponseResult
	 */
	@ExceptionHandler(Exception.class)
	@ResponseBody
	public <T> ResponseResult<T> exceptionHandler(Exception ex) {
		ex.printStackTrace();
		log.error("Unexpected System Exception: {}, {}", HttpCode._503_SERVICE_UNAVAILABLE.getCode(), ex.getMessage());
		log.error("detailed cause: {}", ex.fillInStackTrace());
		return ResponseResult.error(HttpCode._503_SERVICE_UNAVAILABLE, ex.getMessage());
	}


	/**
	 * 唯一索引异常
	 *
	 * @param ex SQL Integrity Constraint Violation Exception
	 * @return ResponseResult
	 */
	@ExceptionHandler({DuplicateKeyException.class})
	@ResponseBody
	public <T> ResponseResult<T> exceptionHandler(SQLIntegrityConstraintViolationException ex, DuplicateKeyException dx) {
		dx.printStackTrace();
		log.error("SQL Integrity Constraint Violation Exception: {}, {}", HttpCode._409_CONFLICT.getCode(), dx.getMessage());
		log.error("detailed reasons: {}", dx.getStackTrace());
		return ResponseResult.error(HttpCode._409_CONFLICT, ex.getMessage());
	}

	/**
	 * sql错误
	 *
	 * @param ex Data Integrity Violation Exception
	 * @return ResponseResult
	 */
	@ExceptionHandler({DataIntegrityViolationException.class})
	@ResponseBody
	public <T> ResponseResult<T> exceptionHandler(SQLException ex, DataIntegrityViolationException dx) {
		dx.printStackTrace();
		log.error("Data Integrity Violation Exception: {}, {}", HttpCode._409_CONFLICT.getCode(), dx.getMessage());
		log.error("detailed reasons: {}", dx.getStackTrace());
		return ResponseResult.error(HttpCode._409_CONFLICT, ex.getMessage());
	}


	/**
	 * 调用方法错误
	 *
	 * @param ex Method Not Allowed
	 * @return ResponseResult
	 */
	@ExceptionHandler({HttpRequestMethodNotSupportedException.class})
	@ResponseBody
	public <T> ResponseResult<T> exceptionHandler(HttpRequestMethodNotSupportedException ex) {
		ex.printStackTrace();
		log.error("HttpRequest Method Not Supported Exception: {}, {}", HttpCode._405_METHOD_NOT_ALLOWED.getCode(), ex.getMessage());
		log.error("detailed cause: {}", ex.fillInStackTrace());
		return ResponseResult.error(HttpCode._405_METHOD_NOT_ALLOWED, ex.getMessage());
	}

}